package com.fowo.api.sys.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fowo.api.sys.annotation.DataActivity;
import com.fowo.api.sys.entity.SysParam;
import com.fowo.api.sys.entity.SysUser;
import com.fowo.api.sys.entity.enums.SysDataActivityAction;
import com.fowo.api.sys.entity.enums.SysParamType;
import com.fowo.api.sys.mapper.SysParamMapper;
import com.fowo.api.sys.mapper.SysUserMapper;
import com.fowo.api.sys.model.SysParamEditModel;
import com.fowo.api.sys.model.SysParamSearch;
import com.fowo.api.sys.model.SysParamValueUsers;
import com.fowo.api.sys.model.SysUserSearch;
import com.fowo.api.sys.service.SysParamService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysParamServiceImpl extends ServiceImpl<SysParamMapper, SysParam> implements SysParamService {

    @Resource
    private SysUserMapper sysUserMapper;

    @Override
    public Page<SysParam> searchPage(SysParamSearch search) {
        return baseMapper.searchPage(search.toPage(), search);
    }

    @Override
    public List<SysParam> search(SysParamSearch search) {
        return baseMapper.search(search);
    }

    @DataActivity(action = SysDataActivityAction.View)
    @Override
    public SysParam getById(Long id) {
        return super.getById(id);
    }

    @DataActivity(action = SysDataActivityAction.Add)
    @Override
    public boolean create(SysParamEditModel model) {
        SysParam sysParam = new SysParam();
        BeanUtils.copyProperties(model, sysParam);
        sysParam.doCreate();
        return save(sysParam);
    }

    @DataActivity(action = SysDataActivityAction.Modified)
    @Override
    public boolean update(SysParamEditModel model) {
        SysParam sysParam = new SysParam();
        BeanUtils.copyProperties(model, sysParam);
        sysParam.doUpdate();
        return updateById(sysParam);
    }

    @DataActivity(action = SysDataActivityAction.Del)
    @Override
    public boolean delete(Long id) {
        return removeById(id);
    }

    public SysParam getByName(String paramName) {
        return baseMapper.selectByName(paramName);
    }

    @Override
    public String getValueByName(String paramName, String defaultValue) {
        SysParam param = getByName(paramName);
        if (param == null || !StringUtils.hasText(param.getValue())) {
            return defaultValue;
        }
        return param.getValue();
    }

    @Override
    public int getIntegerByName(String paramName, int defaultValue) {
        SysParam param = getByName(paramName);
        if (param == null || !StringUtils.hasText(param.getValue())) {
            return defaultValue;
        }
        return Integer.parseInt(param.getValue());
    }

    @Override
    public boolean getSwitchByName(String paramName, boolean defaultSwitch) {
        SysParam param = getByName(paramName);
        if (param == null || !StringUtils.hasText(param.getValue())) {
            return defaultSwitch;
        }
        return Boolean.parseBoolean(param.getValue());
    }

    @Override
    public SysUser getUserByName(String paramName, SysUser defaultUser) {
        SysParam param = getByName(paramName);
        if (param == null || !StringUtils.hasText(param.getValue())) {
            return defaultUser;
        }
        long userId = Long.parseLong(param.getValue());
        SysUser sysUser = sysUserMapper.selectById(userId);
        if (sysUser != null) {
            return sysUser;
        }
        return defaultUser;
    }

    @Override
    public List<SysUser> getUsersByName(String paramName, List<SysUser> defaultUsers) {
        SysParam param = getByName(paramName);
        if (param == null || !StringUtils.hasText(param.getValue())) {
            return defaultUsers;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            SysParamValueUsers sysParamValueUsers = objectMapper.readValue(param.getValue(), SysParamValueUsers.class);
            SysUserSearch search = new SysUserSearch();
            if (SysParamValueUsers.TYPE_ROLE.equals(sysParamValueUsers.getType())) {
                search.setRoleIdIn(sysParamValueUsers.getIds());
            } else if (SysParamValueUsers.TYPE_DEPARTMENT.equals(sysParamValueUsers.getType())) {
                search.setDepartmentIdIn(sysParamValueUsers.getIds());
            } else {
                search.setIds(sysParamValueUsers.getIds());
            }
            return sysUserMapper.search(search).stream().map(svo -> (SysUser)svo).collect(Collectors.toList());
        } catch (JsonProcessingException e) {
        }
        return defaultUsers;
    }

    @Override
    public <T> T getObjectByName(String paramName, Class<T> valueType) {
        SysParam param = getByName(paramName);
        if (param == null || !StringUtils.hasText(param.getValue())) {
            return null;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(param.getValue(), valueType);
        } catch (JacksonException e) {
            e.printStackTrace();
            return null;
        } 
    }

    @Override
    public boolean setObjectByName(String paramName, Object object) throws Exception {
        SysParam param = getByName(paramName);
        if (param == null && object == null) {
            return true;
        }
        if (param != null && object == null) {
            removeById(param.getId());
            return true;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        String value = objectMapper.writeValueAsString(object);
        if (param == null) {
            return create(new SysParamEditModel()
                .setName(paramName)
                .setDescription("系统数据活动（操作日志）设置")
                .setType(SysParamType.Custom)
                .setValue(value)
                );
        } else {
            return update(new SysParamEditModel()
                .setId(param.getId())
                .setValue(value)
            );
        }
    };
}
